"use client"
import { motion, useAnimation } from "framer-motion"
import type React from "react"
import { useEffect, useRef, useState } from "react"
import { ny } from "~/lib/utils"

interface ScratchToRevealProps {
   children: React.ReactNode
   width: number
   height: number
   minScratchPercentage?: number // Minimum percentage of scratched area to be considered as completed (Value between 0 and 100)
   className?: string
   onComplete?: () => void
}

const ScratchToReveal: React.FC<ScratchToRevealProps> = ({
   width,
   height,
   minScratchPercentage = 50,
   onComplete,
   children,
   className,
}) => {
   const canvasRef = useRef<HTMLCanvasElement>(null)
   const [isScratching, setIsScratching] = useState(false)
   const [isComplete, setIsComplete] = useState(false) // New state to track completion

   const controls = useAnimation()

   useEffect(() => {
      const canvas = canvasRef.current
      const ctx = canvas?.getContext("2d")
      if (canvas && ctx) {
         ctx.fillStyle = "#ccc"
         ctx.fillRect(0, 0, canvas.width, canvas.height)
         // Optionally add a background image or gradient
         const gradient = ctx.createLinearGradient(
            0,
            0,
            canvas.width,
            canvas.height,
         )
         gradient.addColorStop(0, "#A97CF8")
         gradient.addColorStop(0.5, "#F38CB8")
         gradient.addColorStop(1, "#FDCC92")
         ctx.fillStyle = gradient
         ctx.fillRect(0, 0, canvas.width, canvas.height)
      }
   }, [])

   useEffect(() => {
      const handleDocumentMouseMove = (event: MouseEvent) => {
         if (!isScratching) return
         scratch(event.clientX, event.clientY)
      }

      const handleDocumentTouchMove = (event: TouchEvent) => {
         if (!isScratching) return
         const touch = event.touches[0]
         scratch(touch.clientX, touch.clientY)
      }

      const handleDocumentMouseUp = () => {
         setIsScratching(false)
         checkCompletion()
      }

      const handleDocumentTouchEnd = () => {
         setIsScratching(false)
         checkCompletion()
      }

      document.addEventListener("mousedown", handleDocumentMouseMove)
      document.addEventListener("mousemove", handleDocumentMouseMove)
      document.addEventListener("touchstart", handleDocumentTouchMove)
      document.addEventListener("touchmove", handleDocumentTouchMove)
      document.addEventListener("mouseup", handleDocumentMouseUp)
      document.addEventListener("touchend", handleDocumentTouchEnd)
      document.addEventListener("touchcancel", handleDocumentTouchEnd)

      return () => {
         document.removeEventListener("mousedown", handleDocumentMouseMove)
         document.removeEventListener("mousemove", handleDocumentMouseMove)
         document.removeEventListener("touchstart", handleDocumentTouchMove)
         document.removeEventListener("touchmove", handleDocumentTouchMove)
         document.removeEventListener("mouseup", handleDocumentMouseUp)
         document.removeEventListener("touchend", handleDocumentTouchEnd)
         document.removeEventListener("touchcancel", handleDocumentTouchEnd)
      }
   }, [isScratching])

   const handleMouseDown = () => setIsScratching(true)

   const handleTouchStart = () => setIsScratching(true)

   const scratch = (clientX: number, clientY: number) => {
      const canvas = canvasRef.current
      const ctx = canvas?.getContext("2d")
      if (canvas && ctx) {
         const rect = canvas.getBoundingClientRect()
         const x = clientX - rect.left + 16 // offset to position the scratched circle with cursor
         const y = clientY - rect.top + 16
         ctx.globalCompositeOperation = "destination-out"
         ctx.beginPath()
         ctx.arc(x, y, 30, 0, Math.PI * 2)
         ctx.fill()
      }
   }

   const checkCompletion = () => {
      if (isComplete) return // Check if already completed

      const canvas = canvasRef.current
      const ctx = canvas?.getContext("2d")
      if (canvas && ctx) {
         const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height)
         const pixels = imageData.data
         const totalPixels = pixels.length / 4
         let clearPixels = 0

         for (let i = 3; i < pixels.length; i += 4) {
            if (pixels[i] === 0) clearPixels++
         }

         const percentage = (clearPixels / totalPixels) * 100

         if (percentage >= minScratchPercentage) {
            setIsComplete(true) // Set complete flag
            ctx.clearRect(0, 0, canvas.width, canvas.height) // Clear the canvas to reveal everything
            startAnimation()
            if (onComplete) onComplete()
         }
      }
   }

   const startAnimation = () => {
      controls.start({
         scale: [1, 1.5, 1],
         rotate: [0, 10, -10, 10, -10, 0],
         transition: { duration: 0.5 },
      })
   }

   return (
      <motion.div
         className={ny("relative select-none", className)}
         style={{
            width,
            height,
            cursor:
               "url(''), auto",
         }}
         animate={controls}
      >
         <canvas
            ref={canvasRef}
            width={width}
            height={height}
            className="absolute left-0 top-0"
            onMouseDown={handleMouseDown}
            onTouchStart={handleTouchStart}
         ></canvas>
         {children}
      </motion.div>
   )
}

export default ScratchToReveal
